package com.api.shop.service.impl;

import com.api.shop.bean.ApiMessage;
import com.api.shop.bean.ApiParam;
import com.api.shop.bean.ApiTestParam;
import com.api.shop.common.ApiStatusEnum;
import com.api.shop.common.NoLoginUrl;
import com.api.shop.common.ReturnData;
import com.api.shop.dao.ApiDao;
import com.api.shop.exception.ParamException;
import com.api.shop.service.MeasureUserService;
import com.api.shop.util.SendPostRequestUtil;
import com.api.shop.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: 杨俊杰
 * @Date: 2019/4/6 16:55
 * @Description:
 */
@Service
@Slf4j
public class MeasureUserServiceImpl implements MeasureUserService {

    @Resource
    private ApiDao apiDao;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public ReturnData getAllUnMeasureApi( HttpServletRequest request) {

        ArrayList<ApiMessage> apiMessageArrayList = apiDao.selectApiMessageByStatus(ApiStatusEnum.TO_BE_TESTED.getValue());
        for(int i = 0; i < apiMessageArrayList.size(); i++){
            ApiMessage message = apiMessageArrayList.get(i);
            ArrayList<ApiParam> apiParamArrayList = apiDao.selectParams(message.getApiId());
            message.setApiParamArrayList(apiParamArrayList);
            apiMessageArrayList.set(i, message);
        }
        return ReturnData.success(apiMessageArrayList);
    }

    @Override
    public ReturnData getOneApi(Integer apiId, HttpServletRequest request) {

        ApiMessage apiMessage = apiDao.selectMessage(apiId);
        if(apiMessage == null){

            throw new ParamException("该api不存在");
        }
        ArrayList<ApiParam> apiParamArrayList = apiDao.selectParams(apiId);
        if(apiParamArrayList==null){

            throw new ParamException("api参数列表不存在");
        }
        apiMessage.setApiParamArrayList(apiParamArrayList);
        return ReturnData.success(apiMessage);
    }

        private ReturnData validParams(String url, ArrayList<ApiTestParam> paramArrayList) {
        //url格式不正确
        if(!url.startsWith("http://") && !url.startsWith("https://"))
        {
            throw new ParamException("url格式不正确，要以http开头");
        }
        ApiMessage apiMessage = apiDao.selectMessageByUrl(url);

        //api不存在
        if(apiMessage == null){
            log.error("api URL不存在 {}",url);
            throw new ParamException("不存在该api");
        }
        ArrayList<ApiParam> apiParamArrayList  = apiDao.selectParams(apiMessage.getApiId());
        //参数个数不正确
        if(paramArrayList.size()!=apiParamArrayList.size()){

            log.error("规定参数个数: {}  实际参数个数 : {}",apiParamArrayList.size(),paramArrayList.size());
            throw new ParamException("api参数与规定个数不符");
        }

        //参数名不匹配

        List<String> ParaKeys = paramArrayList.stream().map(e -> e.getApiParamKey()).collect(Collectors.toList());
        for(ApiParam apiParam : apiParamArrayList){


            if(!ParaKeys.contains(apiParam.getApiParamKey())){
               log.error("参数名与规定值不同 ");
               throw new ParamException("参数名与规定值不同");
            }
        }

    //TODO  api参数格式校验
        return ReturnData.success();
    }

    @Override
    public ReturnData functionalTest(String url,ArrayList<ApiTestParam> apiParamArrayList, HttpServletRequest request) {

        String newUrl="/";
        String[] strings = url.split("/");
        for(int i = 3;i<strings.length;i++){
            if(i!=strings.length-1){
                newUrl+=strings[i]+"/";
            }
            else {
                newUrl += strings[i];
            }
        }
        //加入访问白名单
        NoLoginUrl.add("test"+url,newUrl);
        this.validParams(url,apiParamArrayList);

        Map<String,Object> map = new HashMap<>();
        for(ApiTestParam apiTestParam: apiParamArrayList){

            map.put(apiTestParam.getApiParamKey(),apiTestParam.getApiParamValue());
        }
        String result = null;
        Map<String,String> returnResult = new HashMap<>();
        returnResult.put("测试类型","功能测试");
        returnResult.put("url",url);

        try {
            result = SendPostRequestUtil.sendPost(url,map);
        } catch (FileNotFoundException e) {

            return ReturnData.fail("该Api无法连通，请检查其是否可用");
        }
        if(!result.equals("")){
            returnResult.put("返回值",result);
            NoLoginUrl.remove("test"+url);
            return ReturnData.success(returnResult);
        }
        else{

            throw new ParamException("功能测试失败 返回值为空");
        }

    }

    @Override
    public ReturnData performanceTest(String url,ArrayList<ApiTestParam> apiParamArrayList, HttpServletRequest request) {

        long startTime = System.currentTimeMillis();
        this.functionalTest(url,apiParamArrayList,request);
        long endTime = System.currentTimeMillis();
        float excTime = (float)(endTime-startTime);
        Map<String,String> map = new HashMap<>();
        map.put("测试类型","性能测试");
        map.put("url",url);
        map.put("运行时间",(excTime)+"ms");
        return ReturnData.success(map);
    }

    @Override
    public ReturnData passTest(Integer userId, Integer apiId, HttpServletRequest request) {

        ApiMessage apiMessage  = apiDao.selectMessage(apiId);
        if(apiId == null){

            log.error("该Api不存在");
            throw new ParamException("该Api不存在");
        }
        Integer status = apiMessage.getApiStatus();
        if(status != ApiStatusEnum.TO_BE_TESTED.getValue() && status != ApiStatusEnum.TEST_FAILURE.getValue()){
            log.error("该Api状态无法被测试");
            throw new ParamException("该Api状态无法被测试通过");
        }
        apiDao.updateStatus(apiMessage.getApiId(), ApiStatusEnum.NORMAL.getValue());

        Object object = redisUtil.getHash("api", "apiUserId_" + userId);
        if(object != null){
            ArrayList<ApiMessage> apiMessages = (ArrayList) object;

            for(int i = 0; i < apiMessages.size(); i++){
                ApiMessage message = apiMessages.get(i);

                if(message.getApiId().equals(apiId)){
                    message.setApiStatus(ApiStatusEnum.NORMAL.getValue());
                    apiMessages.set(i, message);

                    redisUtil.setHash("api", "apiUserId_" + userId, apiMessages);
                    log.info("Redis passTest success");
                    break;
                }
            }

        }

        return ReturnData.success();
    }

    @Override
    public ReturnData unPassTest(Integer userId, Integer apiId, HttpServletRequest request) {
        ApiMessage apiMessage  = apiDao.selectMessage(apiId);
        if(apiId == null){

            log.error("该Api不存在");
            throw new ParamException("该Api不存在");
        }

        if(apiMessage.getApiStatus() != ApiStatusEnum.TO_BE_TESTED.getValue()){
            log.error("该Api状态无法被测试");
            throw new ParamException("该Api状态无法被测试不通过");
        }
        apiDao.updateStatus(apiMessage.getApiId(), ApiStatusEnum.TEST_FAILURE.getValue());

        Object object = redisUtil.getHash("api", "apiUserId_" + userId);
        if(object != null){
            ArrayList<ApiMessage> apiMessages = (ArrayList) object;

            for(int i = 0; i < apiMessages.size(); i++){
                ApiMessage message = apiMessages.get(i);

                if(message.getApiId().equals(apiId)){
                    message.setApiStatus(ApiStatusEnum.TEST_FAILURE.getValue());
                    apiMessages.set(i, message);

                    redisUtil.setHash("api", "apiUserId_" + userId, apiMessages);
                    log.info("Redis unPassTest success");
                    break;
                }
            }
        }

        return ReturnData.success();
    }
}
